package com.quintilis31.home.common.utils.crypto;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * 
 * @author JUG Chennai
 *
 */
public final class CryptoUtil {
	
	private static final int ITERATION_COUNT = 500;
	
	private static final ConcurrentHashMap<String, DigestedPassword> PASSWORD_MAP = new ConcurrentHashMap<String, DigestedPassword> ();
	
	static {
		PASSWORD_MAP.put("jothishankarkumar@yahoo.com", null);						
	}
	
	/**
	 * 
	 * @return
	 */
	private static byte[] getRandomSeed(final String email) {
		byte[] randomByte = null;
		final String randomVal = RandomStringUtils.random(8, true, true);
		BASE64Decoder base = new BASE64Decoder();
		try {
			randomByte = base.decodeBuffer(randomVal);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return randomByte;
	}
	
	/**
	 * 
	 * @param password
	 * @return
	 */
	private static String generateBytes(final String password, final String email) {
		if (!PASSWORD_MAP.containsKey(email)) {
			/* throw an exception */
			throw new RuntimeException("Fuck out");
		}	
		
		try {
			DigestedPassword digPass = null;

			if (!isUserAlreadySeeded(email)) {
				/* Get the random seed */
				final byte[] randomSeed = getRandomSeed(email);
				digPass = new DigestedPassword();
				/* Store this in the Digested Password */
				digPass.setSalt(randomSeed);
				generateHashForUser(password, digPass);
				authenticateUser(password, email, digPass);
			}
			else {
				digPass = PASSWORD_MAP.get(email);
				authenticateUser(password, email, digPass);
			}			
		} 
		catch (NoSuchAlgorithmException e) {
			/* Log the original exception */
			e.printStackTrace();
			/* Throw an application specific exception */
		} 
		catch (UnsupportedEncodingException e) {
			/* Log the original exception */
			e.printStackTrace();
			/* Throw an application specific exception */
		}	
		
		return null;		
	}
	
	private static void generateHashForUser(final String password, DigestedPassword digPass) throws NoSuchAlgorithmException, UnsupportedEncodingException {
		digPass.setEncPass(getEncodedPaswordWithSalt(password, digPass.getSalt()));		
	}
	
	private static String getEncodedPaswordWithSalt(final String password, final byte[] salt) throws NoSuchAlgorithmException, UnsupportedEncodingException {
		MessageDigest md = null;
		byte[] pass = null;
		try {
			md = MessageDigest.getInstance("SHA-512");
			md.reset();
			md.update(salt);
			pass = md.digest(password.getBytes("UTF-8"));
			for (int i = 0; i < ITERATION_COUNT; i++) {
			    md.reset();
			    pass = md.digest(pass);
			}
			BASE64Encoder encode = new BASE64Encoder();
			return encode.encode(pass);
		} 
		catch (NoSuchAlgorithmException e) {
			throw e;
		} 
		catch (UnsupportedEncodingException e) {
			throw e;
		}	
		
	}
	
	private static void authenticateUser(final String password, final String email, DigestedPassword digPass) {
		try {
			if (!StringUtils.equals(getEncodedPaswordWithSalt(password, digPass.getSalt()), digPass.getEncPass())) {
				throw new RuntimeException("Fuck OUT!!!");
			}
		} 
		catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("Fuck OUT!!!");			
		} 
		catch (UnsupportedEncodingException e) {
			throw new RuntimeException("Fuck OUT!!!");
		}		
		
				
	}
	
	private static boolean isUserAlreadySeeded(final String email) {
		final DigestedPassword digPass = PASSWORD_MAP.get(email);
		return digPass != null;
	}
	
	public static boolean isUserPasswordValid(final String password, final String email) {
		return false;						
	}

}
